<script lang="ts">
    import {ParamsInterface} from "@/uni_modules/u-popup/components/u-popup/types";
    import {TransitionType} from "@/uni_modules/u-transition/components/u-transition/types";
    import props from "./props";
    import mixin from "@/uni_modules/u-tools/mixin/mixin";
    import mpMixin from "@/uni_modules/u-tools/mixin/mpMixin";
    import UTransition from "@/uni_modules/u-transition/components/u-transition/u-transition.vue";
    import UOverlay from "@/uni_modules/u-overlay/components/u-overlay/u-overlay.vue";
    import USafeAreaPlace from "@/uni_modules/u-safe-area-place/components/u-safe-area-place/u-safe-area-place.vue";
    import UStatusPlace from "@/uni_modules/u-status-place/components/u-status-place/u-status-place.vue";
    import UCapsulePlace from "@/uni_modules/u-capsule-place/components/u-capsule-place/u-capsule-place.vue";

    export default defineComponent({
        // 类名
        name: "u-popup",
        // 组件
        components: {UTransition, UOverlay, USafeAreaPlace, UStatusPlace, UCapsulePlace},
        // 混合
        mixins: [props, mixin, mpMixin],
        // 事件
        emits: ["beforeOpen", "open", "beforeClose", "close"],
        // 暴露方法
        expose: ["open", "close"],
        // 数据
        data()
        {
            return {
                popup: {
                    mode: "center",
                    duration: 300,
                    zIndex: 10000,
                    round: 0,
                    backgroundColor: "#fff",
                    spacing: 0,
                    safeAreaInsetBottom: true,
                    safeAreaInsetTop: false,
                    safeCapsule: false
                } as Record<string, any>,
                showPopup: false, // 是否显示弹出层
                showTrans: false, // 是否显示过渡
                animationSock: false, // 是否动画中
                transparent: null // 透传的数据
            };
        },
        // 监听器
        watch: {
            // 监听显示
            show: {
                handler(value: boolean)
                {
                    if (value)
                    {
                        this.open();
                    }
                    else
                    {
                        this.close();
                    }
                }
            }
        },
        // 计算函数
        computed: {
            // 获取动画类型
            getAnimationType(): TransitionType
            {
                // 当前的动画类型
                let type: TransitionType = "fade";

                // 当前弹窗出现的方式
                switch (this.popup.mode)
                {
                    case "top":
                    {
                        type = "slide-down";

                        break;
                    }
                    case "right":
                    {
                        type = "slide-right";

                        break;
                    }
                    case "bottom":
                    {
                        type = "slide-up";

                        break;
                    }
                    case "left":
                    {
                        type = "slide-left";

                        break;
                    }
                    case "center":
                    {
                        type = "fade";

                        break;
                    }
                    default:
                    {
                        type = "fade";

                        break;
                    }
                }

                return type;
            },
            // 获取内容容器样式
            getControlStyle(): Record<string, any>
            {
                // 当前的内容层样式
                let style: Record<string, any> = {};

                // 背景色
                if (this.popup.backgroundColor)
                {
                    style.backgroundColor = this.popup.backgroundColor;
                }

                // 弹窗圆角
                if (this.popup.round)
                {
                    // 当前圆角
                    const round = this.$u.unit(this.popup.round);

                    // 左侧弹窗
                    if (this.popup.mode === "left")
                    {
                        style.borderTopRightRadius = round;
                        style.borderBottomRightRadius = round;
                    }
                    // 右侧弹窗
                    else if (this.popup.mode === "right")
                    {
                        style.borderTopLeftRadius = round;
                        style.borderBottomLeftRadius = round;
                    }
                    // 上侧弹窗
                    else if (this.popup.mode === "top")
                    {
                        style.borderBottomRightRadius = round;
                        style.borderBottomLeftRadius = round;
                    }
                    // 下侧弹窗
                    else if (this.popup.mode === "bottom")
                    {
                        style.borderTopLeftRadius = round;
                        style.borderTopRightRadius = round;
                    }
                    // 默认弹窗
                    else
                    {
                        style.borderRadius = round;
                    }
                }

                // 两侧弹窗
                if (["left", "right"].includes(this.popup.mode))
                {
                    style.height = "100%";
                    style.display = "flex";
                    style.flexDirection = "column";
                }

                // 内容容器的间距
                if (this.popup.spacing)
                {
                    style.padding = this.$u.unit(this.popup.spacing);
                }

                return style;
            },
            // 获取动画层样式
            getAnimationStyle(): Record<string, any>
            {
                // 当前的动画层样式
                let style: Record<string, any> = {};

                // 当前弹窗出现的方式
                switch (this.popup.mode)
                {
                    case "top":
                    {
                        style = {position: "fixed", left: 0, right: 0, top: 0, zIndex: this.popup.zIndex};

                        break;
                    }
                    case "right":
                    {
                        style = {position: "fixed", right: 0, bottom: 0, top: 0, zIndex: this.zIndex};

                        break;
                    }
                    case "bottom":
                    {
                        style = {position: "fixed", left: 0, right: 0, bottom: 0, zIndex: this.popup.zIndex};

                        break;
                    }
                    case "left":
                    {
                        style = {position: "fixed", left: 0, bottom: 0, top: 0, zIndex: this.popup.zIndex};

                        break;
                    }
                    case "center":
                    {
                        style = {position: "fixed", left: 0, right: 0, bottom: 0, top: 0, display: "flex", justifyContent: "center", alignItems: "center", zIndex: this.popup.zIndex};

                        break;
                    }
                    default:
                    {
                        style = {position: "fixed", left: 0, right: 0, bottom: 0, top: 0, display: "flex", justifyContent: "center", alignItems: "center", zIndex: this.popup.zIndex};

                        break;
                    }
                }

                return style;
            }
        },
        // 方法
        methods: {
            // 打开
            open(params?: ParamsInterface)
            {
                // 判断是否显示，如果是，则不执行
                if (this.showPopup || this.animationSock)
                {
                    return;
                }

                // 执行打开前
                this.$emit("beforeOpen");

                // 显示弹出层
                this.showPopup = true;

                // 开启动画琐
                this.animationSock = true;

                // 当前弹窗显示的方式
                this.popup.mode = params && params.mode && ["center", "top", "bottom", "left", "right"].includes(params.mode) ? params.mode : this.mode;

                // 当前弹窗显示时长
                this.popup.duration = params && params.duration ? params.duration : this.duration;

                // 当前弹窗显示层级
                this.popup.zIndex = params && params.zIndex ? params.zIndex : this.zIndex;

                // 当前弹窗显示的圆角
                this.popup.round = this.$u.unit(params && params.round ? params.round : this.round);

                // 当前弹窗显示的背景色
                this.popup.backgroundColor = params && params.backgroundColor ? params.backgroundColor : this.backgroundColor;

                // 当前弹窗显示的间距
                this.popup.spacing = this.$u.unit(params && params.spacing ? params.spacing : this.spacing);

                // 当前是否为iPhoneX留出底部安全距离
                this.popup.safeAreaInsetBottom = params && params.safeAreaInsetBottom !== undefined ? params.safeAreaInsetBottom : this.safeAreaInsetBottom;

                // 当前是否留出顶部安全距离（状态栏高度）
                this.popup.safeAreaInsetTop = params && params.safeAreaInsetTop !== undefined ? params.safeAreaInsetTop : this.safeAreaInsetTop;

                // 当前是否留出顶部胶囊安全距离（顶部胶囊栏高度）
                this.popup.safeCapsule = params && params.safeCapsule !== undefined ? params.safeCapsule : this.safeCapsule;

                // 透传的数据
                this.transparent = params && params.data ? params.data : null;

                // 延时执行，以便过渡动画顺利执行
                nextTick(() =>
                {
                    // 显示过渡
                    this.showTrans = true;
                });
            },
            // 关闭
            close()
            {
                // 判断是否隐藏，如果是，则不执行
                if (!this.showPopup || this.animationSock)
                {
                    return;
                }

                // 执行关闭前
                this.$emit("beforeClose");

                // 隐藏过渡
                this.showTrans = false;
            },
            // 过渡结束
            transitionEndHandler(type: string)
            {
                // 隐藏
                if (type === "leave")
                {
                    // 隐藏弹出层
                    this.showPopup = false;
                }

                // 关闭动画琐
                this.animationSock = false;

                // 执行对应的事件
                if (type === "enter")
                {
                    this.$emit("open");
                }
                else
                {
                    this.$emit("close");
                }
            }
        }
    });
</script>

<template>
    <!-- 弹出层组件 -->
    <view
        v-if="showPopup"
        :class="[customClass]"
        :style="[
            customStyle,
            {zIndex: popup.zIndex}
        ]"
        class="u-popup"
    >
        <!-- 遮罩 -->
        <u-overlay
            :duration="popup.duration"
            :show="showTrans"
            :z-index="popup.zIndex"
            @click="close"
        />
        <!-- //遮罩 -->

        <!-- 动画层 -->
        <u-transition
            :custom-style="getAnimationStyle"
            :duration="popup.duration"
            :mode="getAnimationType"
            :show="showTrans"
            @tap="close"
            @after-enter="transitionEndHandler('enter')"
            @after-leave="transitionEndHandler('leave')"
        >
            <!-- 内容容器 -->
            <view
                :style="getControlStyle"
                class="control"
                @tap.stop="() => {}"
            >
                <!-- 状态栏占位 -->
                <u-status-place v-if="popup.safeAreaInsetTop && ['top', 'left', 'right'].includes(popup.mode)" />
                <!-- //状态栏占位 -->

                <!-- #ifdef MP -->
                <!-- 胶囊栏占位 -->
                <u-capsule-place v-if="popup.safeCapsule && ['top', 'left', 'right'].includes(popup.mode)" />
                <!-- //胶囊栏占位 -->
                <!-- #endif -->

                <!-- 内容 -->
                <view class="control-area">
                    <!-- 使用模板数据，其实就是作用域插槽 -->
                    <template v-if="useTemplateData">
                        <slot :data="transparent" />
                    </template>
                    <!-- //使用模板数据，其实就是作用域插槽 -->

                    <!-- 默认插槽 -->
                    <template v-else>
                        <slot />
                    </template>
                    <!-- //默认插槽 -->
                </view>
                <!-- //内容 -->

                <!-- 竖屏正方向下的安全区域 -->
                <u-safe-area-place v-if="popup.safeAreaInsetBottom && ['bottom', 'left', 'right'].includes(popup.mode)" />
                <!-- //竖屏正方向下的安全区域 -->
            </view>
            <!-- //内容容器 -->
        </u-transition>
        <!-- //动画层 -->
    </view>
    <!-- //弹出层组件 -->
</template>

<style lang="scss" scoped>
    .u-popup
    {
        position: fixed;
        z-index: 10000;

        // 内容容器
        .control
        {
            overflow: hidden;
            box-sizing: border-box;

            // 内容
            .control-area
            {
                height: 100%;
            }
        }
    }
</style>